﻿#include "SEALineJunctionDialog.h"
#include "ui_SEALineJunctionDialog.h"
#include "SEAJunctionUserDefWidget.h"

#include "OperatorsInterface/ParaWidgetInterfaceOperator.h"

#include "FITK_Kernel/FITKAppFramework/FITKAppFramework.h"
#include "FITK_Kernel/FITKAppFramework/FITKGlobalData.h"
#include "FITK_Kernel/FITKCore/FITKVec3D.h"
#include "FITK_Kernel/FITKCore/FITKVec3DAlg.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsSEAModel.h"
#include "FITK_Component/FITKAcousticsModel/FITKAbstractSEASubSys.h"
#include "FITK_Component/FITKAcousticsModel/FITKSEAAbstractJunction.h"
#include "FITK_Component/FITKAcousticsModel/FITKSEAJunctionLine.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsDiscModel.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsDiscNodeList.h"
#include "FITK_Component/FITKAcousticsPhysics/FITKAcousticsPhysics.h"
#include "FITK_Component/FITKAcousticsPhysics/FITKAcousticsAbsPhysicsProp.h"
#include "FITK_Component/FITKAcousticsPhysics/FITKAcousticsAbsShellPhysicsProp.h"

#include <QList>
#include <QMessageBox>

#define SEALineJunction_SubSysPos Qt::UserRole

namespace GUI
{
    SEALineJunctionDialog::SEALineJunctionDialog(int dataID, EventOper::ParaWidgetInterfaceOperator * oper, bool isCreate) :
        GUIJunctionDialogBase(dataID, oper, isCreate, FITKAPP->getGlobalData()->getMainWindow())
    {
        _ui = new Ui::SEALineJunctionDialog();
        _ui->setupUi(this);

        if (isCreate == false) {
            _currentDataID = dataID;
        }

        init();
    }

    SEALineJunctionDialog::~SEALineJunctionDialog()
    {
        if (_userDefWidget) {
            delete _userDefWidget;
            _userDefWidget = nullptr;
        }
        if (_ui) {
            delete _ui;
            _ui = nullptr;
        }
    }

    void SEALineJunctionDialog::init()
    {
        QStringList connectHeader;
        connectHeader << QString(tr("Connections")) << QString(tr("Over")) << QString(tr("Alpha"));
        _ui->tableWidget_Connect->setColumnCount(3);
        _ui->tableWidget_Connect->setHorizontalHeaderLabels(connectHeader);
        //自适应
        _ui->tableWidget_Connect->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
        //隐藏行表头
        _ui->tableWidget_Connect->verticalHeader()->setVisible(false);
        _ui->tableWidget_Connect->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
        _ui->tableWidget_Connect->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeToContents);

        QStringList nodeHeader;
        nodeHeader << QString(tr("ID")) << QString(tr("Z")) << QString(tr("Y")) << QString(tr("Z"));
        _ui->tableWidget_Nodes->setColumnCount(4);
        _ui->tableWidget_Nodes->setHorizontalHeaderLabels(nodeHeader);
        //自适应
        _ui->tableWidget_Nodes->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
        _ui->tableWidget_Nodes->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
        _ui->label_GeneralImage->setPixmap(QPixmap(":/icons/SEA_Junction_Line.png"));
        _ui->checkBox_EnabledJunction->setChecked(true);
        _userDefWidget = new SEAJunctionUserDefWidget(this);
        _ui->gridLayout_UserDef->addWidget(_userDefWidget);
        _ui->lineEdit_Length->setEnabled(false);

        if (_isCreate) {
            InitCreate();
            setWindowTitle(QString("SEA Line Junction Create"));
        }
        else {
            InitEdit();
            setWindowTitle(QString("SEA Line Junction Edit"));
            _ui->lineEdit_Name->setEnabled(false);
        }
    }

    void SEALineJunctionDialog::setSubsysPoints(QList<int>& pointIDs)
    {
        if (_SEAModel == nullptr && _SEAModel->getSEASubSysManager() == nullptr) false;
        QList<Acoustics::FITKAbstractSEASubSys*>  subSysList = _SEAModel->getSEASubsysConnectedWithNodes(pointIDs, true);
        QList<Acoustics::FITKAbstractSEASubSys*> copySubSysList = subSysList;
        for (Acoustics::FITKAbstractSEASubSys* sys : copySubSysList) {
            if (sys == nullptr) continue;
            auto type = sys->getSEASubSysType();
            switch (type) {
            case Acoustics::FITKAbstractSEASubSys::SEASSNone:
            case Acoustics::FITKAbstractSEASubSys::SEACavity:
            case Acoustics::FITKAbstractSEASubSys::SEASemiIInfiniteFluid: {
                subSysList.removeOne(sys);
                break;
            }
            }
        }

        QList<Acoustics::FITKSEAJunLineConStr> connects = {};
        QList<int> subSysIDs = {};
        for (Acoustics::FITKAbstractSEASubSys* subSysData : subSysList) {
            //子系统id与点id
            Acoustics::FITKSEAJunLineConStr conStr;
            conStr._subSysID = subSysData->getDataObjectID();
            subSysIDs.append(subSysData->getDataObjectID());
            //存储连接信息
            connects.append(conStr);
        }

        updateConnectTable(connects);
        if (_userDefWidget) {
            _userDefWidget->initTable(subSysIDs);
        }
    }

    void SEALineJunctionDialog::setNodes(QList<int>& nodeIDs)
    {
        updateNodeTable(nodeIDs);
    }

    void SEALineJunctionDialog::on_pushButton_Ok_clicked()
    {
        if (_isCreate) {
            if (OKCreate() == false)return;
        }
        else {
            if (OKEdit() == false)return;
        }
        if (_oper) {
            _oper->setArgs(objID_String, _currentDataID);
            _oper->execProfession();
        }
        this->accept();
    }

    void SEALineJunctionDialog::on_pushButton_Cancel_clicked()
    {
        this->reject();
    }

    void SEALineJunctionDialog::slotAlphaOveCheck()
    {

    }

    void SEALineJunctionDialog::InitCreate()
    {
        if (_DiscModel == nullptr && _DiscModel->getJunctionManager() == nullptr)return;
        QString name = "Line-0";
        name = _DiscModel->getJunctionManager()->checkName(name);
        _ui->lineEdit_Name->setText(name);
    }

    void SEALineJunctionDialog::InitEdit()
    {
        if (_DiscModel == nullptr && _DiscModel->getJunctionManager() == nullptr)return;
        Acoustics::FITKSEAJunctionLine* junData = dynamic_cast<Acoustics::FITKSEAJunctionLine*>(_DiscModel->getJunctionManager()->getDataByID(_currentDataID));
        if (junData == nullptr)return;
        QString name = junData->getDataObjectName();
        _ui->lineEdit_Name->setText(name);

        setDataToWidget(junData);
    }

    bool SEALineJunctionDialog::OKCreate()
    {
        if (_DiscModel == nullptr && _DiscModel->getJunctionManager() == nullptr)return false;
        QString name = _ui->lineEdit_Name->text();
        if (_DiscModel->getJunctionManager()->getDataByName(name)) {
            QMessageBox box(QMessageBox::Warning, "", QString(tr("\"%1\" Name exists!")).arg(name), QMessageBox::Ok);
            box.exec();
            return false;
        }

        Acoustics::FITKSEAJunctionLine* junData = new Acoustics::FITKSEAJunctionLine();
        junData->setDataObjectName(name);
        junData->setAutoCreate(false);
        _currentDataID = junData->getDataObjectID();
        getDataFromWidget(junData);
        _DiscModel->getJunctionManager()->appendDataObj(junData);
        return true;
    }

    bool SEALineJunctionDialog::OKEdit()
    {
        if (_DiscModel == nullptr && _DiscModel->getJunctionManager() == nullptr)return false;
        //QString name = _ui->lineEdit_Name->text();
        //if (_DiscModel->getJunctionManager()->getDataByName(name)) {
        //    QMessageBox box(QMessageBox::Warning, "", QString(tr("\"%1\" Name exists!")).arg(name), QMessageBox::Ok);
        //    box.exec();
        //    return false;
        //}
        auto junData = dynamic_cast<Acoustics::FITKSEAJunctionLine*>(_DiscModel->getJunctionManager()->getDataByID(_currentDataID));
        if (junData == nullptr)return false;
        //junData->setDataObjectName(name);
        getDataFromWidget(junData);
        return true;
    }

    void SEALineJunctionDialog::getDataFromWidget(Acoustics::FITKSEAJunctionLine * data)
    {
        if (data == nullptr || _userDefWidget == nullptr)return;

        int conRowCount = _ui->tableWidget_Connect->rowCount();
        QList<Acoustics::FITKSEAJunLineConStr> conInfo;
        for (int i = 0; i < conRowCount; i++) {
            Acoustics::FITKSEAJunLineConStr conStr;
            //子系统id与连接点id
            QTableWidgetItem* item = _ui->tableWidget_Connect->item(i, 0);
            if (item) {
                conStr._subSysID = item->data(SEALineJunction_SubSysPos).toInt();
            }
            //是否角度可修改
            QCheckBox* checkBox = dynamic_cast<QCheckBox*>(_ui->tableWidget_Connect->cellWidget(i, 1));
            if (checkBox) {
                conStr._isAlphaOve = checkBox->isChecked();
            }
            //角度
            item = _ui->tableWidget_Connect->item(i, 2);
            if (item) {
                conStr._alpha = item->text().toDouble();
            }
            conInfo.append(conStr);
        }
        data->replaceConnections(conInfo);

        data->setEnabledJunction(_ui->checkBox_EnabledJunction->isChecked());

        QList<int> nodeIds = {};
        for (int i = 0; i < _ui->tableWidget_Nodes->rowCount(); i++) {
            QTableWidgetItem* item = _ui->tableWidget_Nodes->item(i, 0);
            if (item) {
                nodeIds.append(item->text().toInt());
            }
        }
        data->replectPoints(nodeIds);

        double length = _ui->lineEdit_Length->text().toDouble();
        data->setLineLength(length);

        //存储user-defined界面数据
        _userDefWidget->getDataFromWidget(data);
    }

    void SEALineJunctionDialog::setDataToWidget(Acoustics::FITKSEAJunctionLine * data)
    {
        if (data == nullptr || _userDefWidget == nullptr)return;
        QList<Acoustics::FITKSEAJunLineConStr> conInfo = data->getConnections();
        updateConnectTable(conInfo);

        bool isEnable = data->getEnabledJunction();
        _ui->checkBox_EnabledJunction->setChecked(isEnable);

        QList<int> nodeIDs = data->getPoints();
        updateNodeTable(nodeIDs);

        double length = data->getLineLength();
        _ui->lineEdit_Length->setText(QString::number(length));

        //初始化user-defined界面
        _userDefWidget->initTable(data->getSubSysIds());
        //user-defined中填充数据
        _userDefWidget->setDataToWidget(data);
    }

    void SEALineJunctionDialog::updateConnectTable(QList<Acoustics::FITKSEAJunLineConStr>& junction)
    {
        if (_SEAModel == nullptr && _SEAModel->getSEASubSysManager() == nullptr) false;
        _ui->tableWidget_Connect->setRowCount(0);
        int rowIndex = 0;
        for (Acoustics::FITKSEAJunLineConStr str : junction) {
            Acoustics::FITKAbstractSEASubSys* subSys = _SEAModel->getSEASubSysManager()->getDataByID(str._subSysID);
            if (subSys == nullptr)continue;
            Acoustics::FITKAbstractSEASubSys::SEASubSysType type = subSys->getSEASubSysType();
            _ui->tableWidget_Connect->setRowCount(rowIndex + 1);
            QTableWidgetItem* item = new QTableWidgetItem();
            item->setText(subSys->getDataObjectName());
            item->setData(SEALineJunction_SubSysPos, subSys->getDataObjectID());
            item->setFlags(Qt::ItemIsEnabled);
            _ui->tableWidget_Connect->setItem(rowIndex, 0, item);

            if (type != Acoustics::FITKAbstractSEASubSys::SEABeam) {
                QCheckBox* checkBox = new QCheckBox(this);
                checkBox->setChecked(str._isAlphaOve);
                checkBox->setProperty("row", rowIndex);
                connect(checkBox, SIGNAL(clicked(bool)), this, SLOT(slotAlphaOveCheck()));
                _ui->tableWidget_Connect->setCellWidget(rowIndex, 1, checkBox);

                //item = new QTableWidgetItem();
                //item->setText(subSys->getDataObjectName());
                //item->setData(SEAPointJunction_SubSysPos, subSys->getDataObjectID());
                //item->setData(SEAPointJunction_PointPos, str._pointID);
                //if (str._isAlphaOve) item->setFlags(Qt::ItemIsEnabled);
                //else item->setFlags(Qt::ItemIsEditable);
                //_ui->tableWidget_Connect->setItem(rowIndex, 2, item);
            }
            rowIndex++;
        }
    }

    void SEALineJunctionDialog::updateNodeTable(QList<int>& nodeIDs)
    {
        if (_DiscModel == nullptr && _DiscModel->getNodes() == nullptr) false;
        Acoustics::FITKAcousticsDiscNodeList* nodeList = _DiscModel->getNodes();

        int rowIndex = 0;
        for (int pointID : nodeIDs) {
            Core::FITKNode* node = nodeList->getNodeByID(pointID);
            if (node == nullptr)return;
            _ui->tableWidget_Nodes->setRowCount(rowIndex + 1);
            QTableWidgetItem* item = new QTableWidgetItem();
            item->setText(QString::number(pointID));
            item->setFlags(Qt::ItemIsEnabled);
            _ui->tableWidget_Nodes->setItem(rowIndex, 0, item);

            item = new QTableWidgetItem();
            item->setText(QString::number(node->x()));
            item->setFlags(Qt::ItemIsEnabled);
            _ui->tableWidget_Nodes->setItem(rowIndex, 1, item);

            item = new QTableWidgetItem();
            item->setText(QString::number(node->y()));
            item->setFlags(Qt::ItemIsEnabled);
            _ui->tableWidget_Nodes->setItem(rowIndex, 2, item);

            item = new QTableWidgetItem();
            item->setText(QString::number(node->z()));
            item->setFlags(Qt::ItemIsEnabled);
            _ui->tableWidget_Nodes->setItem(rowIndex, 3, item);
            rowIndex++;
        }

        //计算线长
        double AllLength = 0.0;
        for (int i = 0; i < nodeIDs.size(); i++) {
            if(i == 0)continue;
            Core::FITKNode* lastPoint = nodeList->getNodeByID(nodeIDs[i - 1]);
            Core::FITKNode* curPoint = nodeList->getNodeByID(nodeIDs[i]);
            if (lastPoint == nullptr && curPoint == nullptr)continue;
            double length = Core::Distance(*lastPoint, *curPoint);
            AllLength += length;
        }
        _ui->lineEdit_Length->setText(QString::number(AllLength));
    }
}

